package com.ssy.lingxi.order.serviceimpl.base;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ssy.lingxi.common.constant.basic.*;
import com.ssy.lingxi.common.constant.contract.ContractSourceTypeEnum;
import com.ssy.lingxi.common.constant.marketing.ActivityTypeEnum;
import com.ssy.lingxi.common.constant.order.*;
import com.ssy.lingxi.common.constant.pay.BalanceTypeEnum;
import com.ssy.lingxi.common.constant.settle.SettlementTypeEnum;
import com.ssy.lingxi.common.constant.workflow.WorkflowProcessKindEnum;
import com.ssy.lingxi.order.entity.*;
import com.ssy.lingxi.order.model.bo.PayNodeBO;
import com.ssy.lingxi.order.model.constant.BasePurchaseProcessEnum;
import com.ssy.lingxi.order.model.constant.BaseTradeProcessEnum;
import com.ssy.lingxi.order.repository.*;
import com.ssy.lingxi.order.service.base.IOrderDataInitService;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 初始化订单服务数据
 * @author 万宁
 * @version 2.0.0
 * @date 2021-06-15
 */
@Service
public class OrderDataInitServiceImpl implements IOrderDataInitService {
    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private CountryAreaRepository countryAreaRepository;

    @Resource
    private BaseTradeProcessRepository baseTradeProcessRepository;

    @Resource
    private BasePurchaseProcessRepository basePurchaseProcessRepository;

    @Resource
    private BaseOrderRuleRepository baseOrderRuleRepository;

    @Resource
    private BaseOrderPayChannelRepository baseOrderPayChannelRepository;

    /**
     * 初始化订单服务数据
     */
    @Override
    public void initOrderServiceData() {
        //初始化省市区域
        initCountryArea();

        //初始化基础交易流程
        initBaseTradeProcess();

        //初始化基础采购流程
        initBasePurchaseProcess();

        //初始化平台规则配置
        initBaseOrderRule();

        //初始化支付渠道与支付方式
        initBaseOrderPayChannel();
    }

    /**
     * 初始化省市区域
     */
    private void initCountryArea() {
        try {
            if (countTable("ord_country_area") > 0) {
                return;
            }

            alterSequence("ord_country_area_seq");

            org.springframework.core.io.Resource resource = new ClassPathResource("cn_country_area.json");
            ObjectMapper mapper = new ObjectMapper();
            List<CountryAreaDO> countryAreaList = mapper.readValue(resource.getInputStream(), new TypeReference<List<CountryAreaDO>>() {
            });
            countryAreaList.forEach(area -> area.setId(null));
            countryAreaRepository.saveAll(countryAreaList);
        } catch (Exception e) {
            System.err.println("初始化省市区域表ms_mc_country_area错误:" + e.getMessage());
            System.exit(1);
        }
    }

    /**
     * 初始化基础交易流程
     */
    private void  initBaseTradeProcess() {
        List<BaseTradeProcessDO> tradeProcesses = new ArrayList<>();
        BaseTradeProcessDO process = new BaseTradeProcessDO();
        process.setName("订单多次发货流程");
        process.setProcessKey("order_direct_delivery");
        process.setCode(BaseTradeProcessEnum.order_direct_delivery.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.ORDER_TRADE.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.COMPLEX.getCode());
        process.setSkipFirstStep(true);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("一次支付多次发货流程");
        process.setProcessKey("order_pay_one_deliveries");
        process.setCode(BaseTradeProcessEnum.order_pay_one_deliveries.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.ORDER_TRADE.getCode());
        process.setPayTimes(1);
        process.setProcessKind(WorkflowProcessKindEnum.COMPLEX.getCode());
        process.setSkipFirstStep(true);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(Stream.of(new PayNodeBO(1, 1, "订单提交后", BigDecimal.ZERO)).collect(Collectors.toList()));
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("积分订单流程");
        process.setProcessKey("order_right_point");
        process.setCode(BaseTradeProcessEnum.order_right_point.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.RIGHT_POINT.getCode());
        process.setPayTimes(1);
        process.setProcessKind(WorkflowProcessKindEnum.COMPLEX.getCode());
        process.setSkipFirstStep(true);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(Stream.of(new PayNodeBO(1, 1, "订单提交后", BigDecimal.ZERO)).collect(Collectors.toList()));
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("多次支付多次发货流程");
        process.setProcessKey("order_pay_deliveries");
        process.setCode(BaseTradeProcessEnum.order_pay_deliveries.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.ORDER_TRADE.getCode());
        process.setPayTimes(2);
        process.setProcessKind(WorkflowProcessKindEnum.COMPLEX.getCode());
        process.setSkipFirstStep(true);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(Stream.of(new PayNodeBO(1, 1, "订单提交后", BigDecimal.ZERO), new PayNodeBO(2,2,"收货后", BigDecimal.ZERO)).collect(Collectors.toList()));
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("订单审核多次支付多次发货流程");
        process.setProcessKey("order_validate_pay_seven_deliveries");
        process.setCode(BaseTradeProcessEnum.order_validate_pay_seven_deliveries.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.ORDER_TRADE.getCode());
        process.setPayTimes(7);
        process.setProcessKind(WorkflowProcessKindEnum.COMPLEX.getCode());
        process.setSkipFirstStep(true);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(Stream.of(new PayNodeBO(1, 1, "首付", BigDecimal.ZERO), new PayNodeBO(1,2,"分期支付", BigDecimal.ZERO), new PayNodeBO(1,3,"分期支付", BigDecimal.ZERO), new PayNodeBO(1,4,"分期支付", BigDecimal.ZERO), new PayNodeBO(2,5,"收货后支付", BigDecimal.ZERO), new PayNodeBO(2,6,"尾款支付", BigDecimal.ZERO), new PayNodeBO(2,7,"质保金支付", BigDecimal.ZERO)).collect(Collectors.toList()));
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("售后换货处理流程1(含收发货单)");
        process.setProcessKey("after_sale_replace_goods_outer_verify_ext");
        process.setCode(BaseTradeProcessEnum.after_sale_replace_goods_outer_verify_ext.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.AFTER_SALES_EXCHANGES.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("售后换货处理流程2(无收发货单)");
        process.setProcessKey("after_sale_replace_goods_manual_delivery_ext");
        process.setCode(BaseTradeProcessEnum.after_sale_replace_goods_manual_delivery_ext.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.AFTER_SALES_EXCHANGES.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("售后换货处理流程3(线下物流)");
        process.setProcessKey("after_sale_replace_goods_outer_verify_offline_logistics_ext");
        process.setCode(BaseTradeProcessEnum.after_sale_replace_goods_outer_verify_offline_logistics_ext.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.AFTER_SALES_EXCHANGES.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("售后退货处理流程1(含收发货单)");
        process.setProcessKey("after_sale_return_goods_outer_verify_ext");
        process.setCode(BaseTradeProcessEnum.after_sale_return_goods_outer_verify_ext.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.AFTER_SALES_RETURNS.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("售后退货处理流程2(线下物流)");
        process.setProcessKey("after_sale_return_goods_outer_verify_offline_logistics_ext");
        process.setCode(BaseTradeProcessEnum.after_sale_return_goods_outer_verify_offline_logistics_ext.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.AFTER_SALES_RETURNS.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("售后退货处理流程3(无收发货单)");
        process.setProcessKey("after_sale_return_goods_manual_delivery_ext");
        process.setCode(BaseTradeProcessEnum.after_sale_return_goods_manual_delivery_ext.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.AFTER_SALES_RETURNS.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("售后退货处理流程4(平台审核无收发货单)");
        process.setProcessKey("after_sale_return_goods_pf_manual_delivery_ext");
        process.setCode(BaseTradeProcessEnum.after_sale_return_goods_pf_manual_delivery_ext.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.AFTER_SALES_RETURNS.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("加工生产处理流程");
        process.setProcessKey("pno_outer_verify_ext");
        process.setCode(BaseTradeProcessEnum.pno_outer_verify_ext.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.PRODUCTION.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("加工生产手工发货处理流程");
        process.setProcessKey("pno_manual_delivery_outer_verify_ext");
        process.setCode(BaseTradeProcessEnum.pno_manual_delivery_outer_verify_ext.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.PRODUCTION.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("售后维修流程");
        process.setProcessKey("after_sale_repair_inner_verify");
        process.setCode(BaseTradeProcessEnum.after_sale_repair_inner_verify.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.AFTER_SALES_MAINTENANCE.getCode());
        process.setPayTimes(0);
        process.setProcessKind(WorkflowProcessKindEnum.INTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(new ArrayList<>());
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("多次支付多次发货有收发货单线上物流流程");
        process.setProcessKey("order_pay_online_deliveries");
        process.setCode(BaseTradeProcessEnum.order_pay_online_deliveries.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.ORDER_TRADE.getCode());
        process.setPayTimes(1);
        process.setProcessKind(WorkflowProcessKindEnum.COMPLEX.getCode());
        process.setSkipFirstStep(true);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(Stream.of(new PayNodeBO(1, 1, "订单提交后", BigDecimal.ZERO)).collect(Collectors.toList()));
        tradeProcesses.add(process);

        process = new BaseTradeProcessDO();
        process.setName("跨境电商进口交易流程");
        process.setProcessKey("order_commerce_import");
        process.setCode(BaseTradeProcessEnum.order_commerce_import.getCode());
        process.setProcessType(OrderTradeProcessTypeEnum.ORDER_COMMERCE_IMPORT.getCode());
        process.setPayTimes(1);
        process.setProcessKind(WorkflowProcessKindEnum.COMPLEX.getCode());
        process.setSkipFirstStep(true);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        process.setPayNodes(Stream.of(new PayNodeBO(1, 1, "订单提交后", BigDecimal.ZERO)).collect(Collectors.toList()));
        tradeProcesses.add(process);

        List<BaseTradeProcessDO> tradeProcessList = baseTradeProcessRepository.findAll();
        tradeProcessList.forEach(tradeProcess -> tradeProcesses.stream().filter(p -> p.getProcessKey().equals(tradeProcess.getProcessKey())).findFirst().ifPresent(p -> {
            tradeProcess.setCode(p.getCode());
            tradeProcess.setProcessKind(p.getProcessKind());
            tradeProcess.setProcessType(p.getProcessType());
            tradeProcess.setSkipFirstStep(p.getSkipFirstStep());
            tradeProcess.setPayTimes(p.getPayTimes());
            tradeProcess.setName(p.getName());
            tradeProcess.setStatus(p.getStatus());
            tradeProcess.setPayNodes(p.getPayNodes());
        }));

        tradeProcessList.addAll(tradeProcesses.stream().filter(p -> tradeProcessList.stream().noneMatch(tp -> tp.getProcessKey().equals(p.getProcessKey()))).collect(Collectors.toList()));

        baseTradeProcessRepository.saveAll(tradeProcessList);
    }

    /**
     * 初始化基础采购流程
     */
    private void initBasePurchaseProcess() {
        List<BasePurchaseProcessDO> purchaseProcesses = new ArrayList<>();
        BasePurchaseProcessDO process = new BasePurchaseProcessDO();
        process.setName("采购询价交易流程");
        process.setProcessKey("order_direct_delivery");
        process.setCode(BasePurchaseProcessEnum.order_direct_delivery.getCode());
        process.setProcessType(OrderPurchaseProcessTypeEnum.ORDER_TRADE.getCode());
        process.setProcessKind(WorkflowProcessKindEnum.COMPLEX.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        purchaseProcesses.add(process);

        process = new BasePurchaseProcessDO();
        process.setName("请购单下单流程");
        process.setProcessKey("order_requisition");
        process.setCode(BasePurchaseProcessEnum.order_requisition.getCode());
        process.setProcessType(OrderPurchaseProcessTypeEnum.REQUISITION.getCode());
        process.setProcessKind(WorkflowProcessKindEnum.COMPLEX.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        purchaseProcesses.add(process);

        process = new BasePurchaseProcessDO();
        process.setName("售后换货处理流程1(含收发货单)");
        process.setProcessKey("after_sale_replace_goods_outer_verify_ext");
        process.setCode(BasePurchaseProcessEnum.after_sale_replace_goods_outer_verify_ext.getCode());
        process.setProcessType(OrderPurchaseProcessTypeEnum.AFTER_SALES_EXCHANGES.getCode());
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        purchaseProcesses.add(process);

        process = new BasePurchaseProcessDO();
        process.setName("售后换货处理流程2(无收发货单)");
        process.setProcessKey("after_sale_replace_goods_manual_delivery_ext");
        process.setCode(BasePurchaseProcessEnum.after_sale_replace_goods_manual_delivery_ext.getCode());
        process.setProcessType(OrderPurchaseProcessTypeEnum.AFTER_SALES_EXCHANGES.getCode());
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        purchaseProcesses.add(process);

        process = new BasePurchaseProcessDO();
        process.setName("售后换货处理流程3(线下物流)");
        process.setProcessKey("after_sale_replace_goods_outer_verify_offline_logistics_ext");
        process.setCode(BasePurchaseProcessEnum.after_sale_replace_goods_outer_verify_offline_logistics_ext.getCode());
        process.setProcessType(OrderPurchaseProcessTypeEnum.AFTER_SALES_EXCHANGES.getCode());
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        purchaseProcesses.add(process);


        process = new BasePurchaseProcessDO();
        process.setName("售后退货处理流程1(合同含收发货单)");
        process.setProcessKey("after_sale_return_goods_contract_verify_ext");
        process.setCode(BasePurchaseProcessEnum.after_sale_return_goods_contract_verify_ext.getCode());
        process.setProcessType(OrderPurchaseProcessTypeEnum.AFTER_SALES_RETURNS.getCode());
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        purchaseProcesses.add(process);

        process = new BasePurchaseProcessDO();
        process.setName("售后退货处理流程2(合同线下物流)");
        process.setProcessKey("after_sale_return_goods_outer_verify_contract_offline_logistics_ext");
        process.setCode(BasePurchaseProcessEnum.after_sale_return_goods_outer_verify_contract_offline_logistics_ext.getCode());
        process.setProcessType(OrderPurchaseProcessTypeEnum.AFTER_SALES_RETURNS.getCode());
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        purchaseProcesses.add(process);

        process = new BasePurchaseProcessDO();
        process.setName("售后退货处理流程3(合同无收发货单)");
        process.setProcessKey("after_sale_return_goods_contract_manual_delivery_ext");
        process.setCode(BasePurchaseProcessEnum.after_sale_return_goods_contract_manual_delivery_ext.getCode());
        process.setProcessType(OrderPurchaseProcessTypeEnum.AFTER_SALES_RETURNS.getCode());
        process.setProcessKind(WorkflowProcessKindEnum.EXTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        purchaseProcesses.add(process);

        process = new BasePurchaseProcessDO();
        process.setName("售后维修流程");
        process.setProcessKey("after_sale_repair_inner_verify");
        process.setCode(BasePurchaseProcessEnum.after_sale_repair_inner_verify.getCode());
        process.setProcessType(OrderPurchaseProcessTypeEnum.AFTER_SALES_MAINTENANCE.getCode());
        process.setProcessKind(WorkflowProcessKindEnum.INTERNAL.getCode());
        process.setSkipFirstStep(false);
        process.setStatus(EnableDisableStatus.ENABLE.getCode());
        purchaseProcesses.add(process);

        List<BasePurchaseProcessDO> purchaseProcessList = basePurchaseProcessRepository.findAll();
        purchaseProcessList.forEach(purchaseProcess -> purchaseProcesses.stream().filter(p -> p.getProcessKey().equals(purchaseProcess.getProcessKey())).findFirst().ifPresent(p -> {
            purchaseProcess.setCode(p.getCode());
            purchaseProcess.setProcessKind(p.getProcessKind());
            purchaseProcess.setProcessType(p.getProcessType());
            purchaseProcess.setSkipFirstStep(p.getSkipFirstStep());
            purchaseProcess.setName(p.getName());
            purchaseProcess.setStatus(p.getStatus());
        }));

        purchaseProcessList.addAll(purchaseProcesses.stream().filter(p -> purchaseProcessList.stream().noneMatch(tp -> tp.getProcessKey().equals(p.getProcessKey()))).collect(Collectors.toList()));
        basePurchaseProcessRepository.saveAll(purchaseProcessList);
    }

    /**
     * 初始化平台规则配置
     */
    private void initBaseOrderRule() {
        if(countTable("ord_base_order_rule") == 0) {
            alterSequence("ord_base_order_rule_seq");
        }

        List<BaseOrderRuleDO> orderRules = new ArrayList<>();
        //资金归集模式
        orderRules.addAll(Arrays.stream(FundModeEnum.values()).sorted(Comparator.comparingInt(FundModeEnum::getCode)).map(fundMode -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.FUND.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.FUND.getName());
            orderRule.setMethodCode(fundMode.getCode());
            orderRule.setMethodName(fundMode.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //库存扣减策略
        orderRules.addAll(Arrays.stream(InventoryReduceTypeEnum.values()).sorted(Comparator.comparingInt(InventoryReduceTypeEnum::getCode)).map(reduceType -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.INVENTORY.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.INVENTORY.getName());
            orderRule.setMethodCode(reduceType.getCode());
            orderRule.setMethodName(reduceType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //下单模式
        orderRules.addAll(Arrays.stream(OrderModeEnum.values()).sorted(Comparator.comparingInt(OrderModeEnum::getCode)).map(orderMode -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.ORDER_MODE.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.ORDER_MODE.getName());
            orderRule.setMethodCode(orderMode.getCode());
            orderRule.setMethodName(orderMode.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //订单类型
        orderRules.addAll(Arrays.stream(OrderTypeEnum.values()).sorted(Comparator.comparingInt(OrderTypeEnum::getCode)).map(orderType -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.ORDER_TYPE.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.ORDER_TYPE.getName());
            orderRule.setMethodCode(orderType.getCode());
            orderRule.setMethodName(orderType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //营销活动类型
        orderRules.addAll(Arrays.stream(ActivityTypeEnum.values()).filter(e -> !e.getCode().equals(0)).sorted(Comparator.comparingInt(ActivityTypeEnum::getCode)).map(activityType -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.MARKETING.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.MARKETING.getName());
            orderRule.setMethodCode(activityType.getCode());
            orderRule.setMethodName(activityType.getMessage());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //结算方式
        orderRules.addAll(Arrays.stream(OrderSettlementEnum.values()).sorted(Comparator.comparingInt(OrderSettlementEnum::getCode)).map(settlement -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.SETTLEMENT.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.SETTLEMENT.getName());
            orderRule.setMethodCode(settlement.getCode());
            orderRule.setMethodName(settlement.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //品类与属性使用方式
        orderRules.addAll(Arrays.stream(OrderCatetoryAttributeEnum.values()).sorted(Comparator.comparingInt(OrderCatetoryAttributeEnum::getCode)).map(attribute -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.PRODUCT_CATEGORY.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.PRODUCT_CATEGORY.getName());
            orderRule.setMethodCode(attribute.getCode());
            orderRule.setMethodName(attribute.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //采购询源类型
        orderRules.addAll(Arrays.stream(ContractSourceTypeEnum.values()).filter(e -> !e.getCode().equals(0)).sorted(Comparator.comparingInt(ContractSourceTypeEnum::getCode)).map(sourceType -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.PURCHASE_SOURCE.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.PURCHASE_SOURCE.getName());
            orderRule.setMethodCode(sourceType.getCode());
            orderRule.setMethodName(sourceType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //采购合同付款方式
        orderRules.addAll(Arrays.stream(PurchaseContractPayTypeEnum.values()).sorted(Comparator.comparingInt(PurchaseContractPayTypeEnum::getCode)).map(contractPayType -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.PURCHASE_CONTRACT.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.PURCHASE_CONTRACT.getName());
            orderRule.setMethodCode(contractPayType.getCode());
            orderRule.setMethodName(contractPayType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //结算支付方式
        orderRules.addAll(Arrays.stream(SettlementTypeEnum.values()).sorted(Comparator.comparingInt(SettlementTypeEnum::getCode)).map(settlementType -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.SETTLEMENT_TYPE.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.SETTLEMENT_TYPE.getName());
            orderRule.setMethodCode(settlementType.getCode());
            orderRule.setMethodName(settlementType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        //账户余额类型
        orderRules.addAll(Arrays.stream(BalanceTypeEnum.values()).sorted(Comparator.comparingInt(BalanceTypeEnum::getCode)).map(balanceType -> {
            BaseOrderRuleDO orderRule = new BaseOrderRuleDO();
            orderRule.setRuleType(PlatformRuleTypeEnum.BALANCE_TYPE.getCode());
            orderRule.setRuleName(PlatformRuleTypeEnum.BALANCE_TYPE.getName());
            orderRule.setMethodCode(balanceType.getCode());
            orderRule.setMethodName(balanceType.getName());
            orderRule.setStatus(EnableDisableStatus.ENABLE.getCode());
            return orderRule;
        }).collect(Collectors.toList()));

        List<BaseOrderRuleDO> baseOrderRules = baseOrderRuleRepository.findAll();
        baseOrderRules.forEach(baseOrderRule -> orderRules.stream().filter(orderRule -> orderRule.getRuleType().equals(baseOrderRule.getRuleType()) && orderRule.getMethodCode().equals(baseOrderRule.getMethodCode())).findFirst().ifPresent(orderRule -> {
            baseOrderRule.setRuleName(orderRule.getRuleName());
            baseOrderRule.setMethodName(orderRule.getMethodName());
        }));

        baseOrderRules.addAll(orderRules.stream().filter(orderRule -> baseOrderRules.stream().noneMatch(baseOrderRule -> baseOrderRule.getRuleType().equals(orderRule.getRuleType()) && baseOrderRule.getMethodCode().equals(orderRule.getMethodCode()))).collect(Collectors.toList()));
        baseOrderRuleRepository.saveAll(baseOrderRules);
    }

    /**
     * 初始化支付方式与支付渠道配置
     */
    private void initBaseOrderPayChannel() {
        if(countTable("ord_base_order_pay_channel") == 0) {
            alterSequence("ord_base_order_pay_channel_seq");
        }

        List<OrderPayTypeEnum> payTypes = Arrays.stream(OrderPayTypeEnum.values()).filter(OrderPayTypeEnum::getUseForPaymentSetting).sorted(Comparator.comparingInt(OrderPayTypeEnum::getCode)).collect(Collectors.toList());
        List<BaseOrderPayChannelDO> baseOrderPayChannels = payTypes.stream().flatMap(payType -> payType.getPayChannels().stream().sorted(Comparator.comparingInt(OrderPayChannelEnum::getCode)).map(payChannel -> {
            BaseOrderPayChannelDO baseOrderPayChannel = new BaseOrderPayChannelDO();
            baseOrderPayChannel.setPayType(payType.getCode());
            baseOrderPayChannel.setPayTypeName(payType.getName());
            baseOrderPayChannel.setPayChannel(payChannel.getCode());
            baseOrderPayChannel.setPayChannelName(payChannel.getName());
            baseOrderPayChannel.setStatus(EnableDisableStatus.ENABLE.getCode());
            return baseOrderPayChannel;
        })).collect(Collectors.toList());

        List<BaseOrderPayChannelDO> payChannels = baseOrderPayChannelRepository.findAll();
        payChannels.forEach(payChannel -> baseOrderPayChannels.stream().filter(baseOrderPayChannel -> baseOrderPayChannel.getPayType().equals(payChannel.getPayType()) && baseOrderPayChannel.getPayChannel().equals(payChannel.getPayChannel())).findFirst().ifPresent(baseOrderPayChannel -> {
            payChannel.setPayTypeName(baseOrderPayChannel.getPayTypeName());
            payChannel.setPayChannelName(baseOrderPayChannel.getPayChannelName());
        }));

        payChannels.addAll(baseOrderPayChannels.stream().filter(baseOrderPayChannel -> payChannels.stream().noneMatch(payChannel -> payChannel.getPayType().equals(baseOrderPayChannel.getPayType()) && payChannel.getPayChannel().equals(baseOrderPayChannel.getPayChannel()))).collect(Collectors.toList()));
        baseOrderPayChannelRepository.saveAll(payChannels);
    }

    /**
     * 执行 select count(id) from table 语句
     * @param dbTableName 数据库的表名称
     * @return 表数据行数
     */
    private long countTable(String dbTableName) {
        String sql = "select count(id) as total from " + dbTableName + ";";
        SqlRowSet sqlRowSet = jdbcTemplate.queryForRowSet(sql);
        long total = 0;
        while (sqlRowSet.next()) {
            total = sqlRowSet.getLong("total");
        }
        return total;
    }

    /**
     * 更改序列值为1
     * @param sequenceName 序列名称
     */
    private void alterSequence(String sequenceName) {
        String sql = "alter sequence " + sequenceName + " restart with 1";
        jdbcTemplate.execute(sql);
    }
}
